package service

import (
	"log"
	"reflect"
	"strings"
)

type Manager struct {
	services  map[string]*serviceInfo
	handler   func(param reflect.Type)
}

func NewManager(handler func(param reflect.Type)) *Manager {
	manager := new(Manager)
	manager.services = make(map[string]*serviceInfo)
	manager.handler = handler

	return manager
}

func (manager *Manager) Register(s service) {
	if s == nil {
		log.Fatalf("service is nil")
	}

	name := s.Name()
	if _, exists := manager.services[name]; exists {
		log.Fatalf("service is already exists, %v", name)
	}

	serviceType := reflect.TypeOf(s)
	serviceValue := reflect.ValueOf(s)
	info := newServiceInfo()

	for i := 0; i < serviceType.NumMethod(); i++ {
		methodType := serviceType.Method(i)
		methodName := methodType.Name
		methodValue := serviceValue.MethodByName(methodName)

		info.register(
			methodName,
			methodType,
			methodValue,
			manager.handler,
		)
	}

	manager.services[name] = info
}

func (manager *Manager) Get(name string) (result *Method, exists bool) {
	parts := strings.Split(name, ".")
	if len(parts) != 2 {
		return
	}

	serviceName := parts[0]
	var info *serviceInfo
	if info, exists = manager.services[serviceName]; !exists {
		return
	}

	methodName := parts[1]
	if result, exists = info.get(methodName); !exists {
		return
	}

	return
}
